﻿/*
 * Toast8
 * All rights reserved
 * Copyright (C) 2014 Peter Nylander
 */

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using Toast8.SpotifyHelper;

namespace Toast8
{
    public class ImageCache
    {
        public string CachePath { get; private set; }
        public string DefaultImage { get; private set; }

        private Dictionary<string, string> resourceCache = new Dictionary<string, string>();

        public ImageCache(string cachePath)
        {
            this.CachePath = cachePath;

            // Create cover art cache folder
            if (!Directory.Exists(this.CachePath))
            {
                Directory.CreateDirectory(this.CachePath);
            }

            var values = Enum.GetValues(typeof(CoverArtSize));

            foreach (CoverArtSize s in values)
            {
                if (!Directory.Exists(this.CachePath + "/" + s.ToString()))
                {
                    Directory.CreateDirectory(this.CachePath + "/" + s.ToString());
                }
            }
        }

        public void Add(Uri uri)
        {

        }

        public void Remove(Uri uri)
        {

        }

        public async Task<string> Get(Resource res)
        {
            // Load url from memory cache
            // if not in memory cache
            // or if not in file cache
            // download image
            string imageKey = GetImageKey(res.Uri);

            StringBuilder sb = new StringBuilder();
            sb.Append(CachePath);
            sb.Append("/");
            sb.Append(imageKey);
            sb.Append(".jpg");

            if (resourceCache.ContainsKey(res.Uri))
            {
                return resourceCache[res.Uri];
            }

            // Check if file is in cache
            if (!File.Exists(sb.ToString()))
            {
                // Download
                await DownloadImage(res.ThumbnailUrl, sb.ToString());
                resourceCache.Add(res.Uri, sb.ToString());
            }
            else
            {
                // Cache hit
                return Path.GetFullPath(sb.ToString());
            }

            return sb.ToString();
        }

        public async Task<string> Get(Resource res, CoverArtSize size)
        {
            string artworkUrl = string.Empty;

            switch (size)
            {
                case CoverArtSize.Size300:
                    artworkUrl = res.ThumbnailUrl.Replace("cover", "300");
                    break;
                case CoverArtSize.Size120:
                    artworkUrl = res.ThumbnailUrl.Replace("cover", "120");
                    break;
            }

            string imageKey = GetImageKey(artworkUrl);

            StringBuilder sb = new StringBuilder();
            sb.Append(CachePath);
            sb.Append("\\");
            sb.Append(size.ToString());
            sb.Append("\\");
            sb.Append(imageKey);
            sb.Append(".jpg");

            if (resourceCache.ContainsKey(artworkUrl))
            {
                return resourceCache[artworkUrl];
            }

            // Check if file is in cache
            if (!File.Exists(sb.ToString()))
            {
                // Download
                await DownloadImage(artworkUrl, sb.ToString()).ConfigureAwait(false);
                resourceCache.Add(artworkUrl, sb.ToString());
            }
            else
            {
                // Cache hit
                return Path.GetFullPath(sb.ToString());
            }

            return sb.ToString();
        }

        public string GetLargeArtwork(Resource res)
        {
            string path = Get(res, CoverArtSize.Size300).Result;
            return path;
        }

        private string GetImageKey(string imageUri)
        {
            var imageUriBytes = Encoding.UTF8.GetBytes(imageUri);
            var hash = new SHA1Managed().ComputeHash(imageUriBytes);
            return BitConverter.ToString(hash).Replace("-", "");
        }

        /// <summary>
        /// Fetches an image from the file cache, if file is not found in the cache it will be downloaded
        /// </summary>
        /// <param name="url"></param>
        /// <param name="fileName"></param>
        /// <returns></returns>
        private async Task DownloadImage(string uri, string fileName)
        {
            try
            {
                HttpClient httpClient = new HttpClient();
                httpClient.Timeout = TimeSpan.FromSeconds(5);

                HttpResponseMessage response = await httpClient.GetAsync(uri).ConfigureAwait(false);
                response.EnsureSuccessStatusCode();

                Stream result = await response.Content.ReadAsStreamAsync();

                using (Stream fileStream = File.Create(fileName))
                {
                    await result.CopyToAsync(fileStream);
                }
            }
            catch (Exception)
            {             
            }
        }
    }
}
